package pers.sun.oauthclient.util;

import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.utils.OAuthUtils;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by linfx7 on 2016/4/8 008.
 */
public class HttpsClient implements HttpClient {

    private static TrustManager trustAllCerts = new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
    };

    private static HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String s, SSLSession sslSession) {
            return true;
        }
    };

    public HttpsClient() {
    }

    public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers, String requestMethod, Class<T> responseClass)
            throws OAuthSystemException, OAuthProblemException {
        String responseBody = null;
        URLConnection c = null;
        boolean responseCode = false;

        int responseCode1;
        try {
            URL e = new URL(request.getLocationUri());
            c = e.openConnection();
            responseCode1 = -1;
            if(c instanceof HttpsURLConnection) {
                HttpsURLConnection httpsURLConnection = (HttpsURLConnection)c;

                //trust manager
                SSLContext sslcontext = SSLContext.getInstance("TLS");
                sslcontext.init(null, new TrustManager[]{trustAllCerts}, null);
                httpsURLConnection.setSSLSocketFactory(sslcontext.getSocketFactory());
                //host name verifier
                httpsURLConnection.setHostnameVerifier(allHostsValid);

                Iterator inputStream;
                Map.Entry pw;
                if(headers != null && !headers.isEmpty()) {
                    inputStream = headers.entrySet().iterator();

                    while(inputStream.hasNext()) {
                        pw = (Map.Entry)inputStream.next();
                        httpsURLConnection.addRequestProperty((String)pw.getKey(), (String)pw.getValue());
                    }
                }

                if(request.getHeaders() != null) {
                    inputStream = request.getHeaders().entrySet().iterator();

                    while(inputStream.hasNext()) {
                        pw = (Map.Entry)inputStream.next();
                        httpsURLConnection.addRequestProperty((String)pw.getKey(), (String)pw.getValue());
                    }
                }

                if(!OAuthUtils.isEmpty(requestMethod)) {
                    httpsURLConnection.setRequestMethod(requestMethod);
                    if(requestMethod.equals("POST")) {
                        httpsURLConnection.setDoOutput(true);
                        OutputStream inputStream1 = httpsURLConnection.getOutputStream();
                        PrintWriter pw1 = new PrintWriter(inputStream1);
                        pw1.print(request.getBody());
                        pw1.flush();
                        pw1.close();
                    }
                } else {
                    httpsURLConnection.setRequestMethod("GET");
                }

                httpsURLConnection.connect();
                responseCode1 = httpsURLConnection.getResponseCode();
                InputStream inputStream2;
                if(responseCode1 != 400 && responseCode1 != 401) {
                    inputStream2 = httpsURLConnection.getInputStream();
                } else {
                    inputStream2 = httpsURLConnection.getErrorStream();
                }

                responseBody = OAuthUtils.saveStreamAsString(inputStream2);
            }
        } catch (IOException var12) {
            throw new OAuthSystemException(var12);
        } catch (Exception e) {
            throw OAuthProblemException.error("https error");
        }

        return OAuthClientResponseFactory.createCustomResponse(responseBody, c.getContentType(), responseCode1, responseClass);
    }

    public void shutdown() {

    }
}


